﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace WssEvents
{

    /// <summary>
    /// 事件处理核心，可以接受任意的Delegate 保存
    /// v1.0.1 修改 DynamicInvoke 改为 Method.Invoke, 优化40%性能
    /// </summary>
    public class EventTarget : IDisposable
    {

        private Dictionary<string, Delegate> ListenerDictionary = new Dictionary<string, Delegate>();

        public void Listen(string eventType, Delegate Callback)
        {
            Delegate callback;
            if (ListenerDictionary.TryGetValue(eventType, out callback))
            {
                if (callback != Callback) //(callback.Method != Callback.Method)
                {
                    if (callback.GetType() != Callback.GetType())
                    {
                        Debug.LogError("Linsten: " + eventType + " Error,You Must linsten Same Signed Function");
                        return;
                    }
                    callback = Delegate.Combine(callback, Callback);
                    ListenerDictionary.Remove(eventType);
                    ListenerDictionary.Add(eventType, callback);
                }
            }
            else
            {
                ListenerDictionary.Add(eventType, Callback);
            }
        }

        public void Remove(string eventType, Delegate Callback)
        {
            Delegate callback;
            if (ListenerDictionary.TryGetValue(eventType, out callback))
            {

                callback = Delegate.Remove(callback, Callback);

                if (callback == null)
                {
                    if (ListenerDictionary.ContainsKey(eventType))
                        ListenerDictionary.Remove(eventType);
                }
                else
                {
                    ListenerDictionary.Remove(eventType);
                    ListenerDictionary.Add(eventType, callback);
                }
            }
        }

        public void Dispatcher(string eventType, params object[] args)
        {
            Delegate callback;
            if (ListenerDictionary.TryGetValue(eventType, out callback))
            {
                for (int i = 0; i < callback.GetInvocationList().Length; i++)
                {
                    var targ = callback.GetInvocationList()[i];
                    if (targ.Target == null)
                    {
                        targ.DynamicInvoke(args);
                    }
                    else
                    {
                        targ.Method?.Invoke(targ.Target, args); //性能比 DynamicInvoke 好一些
                    }
                }
                
            }
        }

        public void RemoveTarget(object obj)
        {
            foreach (var item in ListenerDictionary.ToList())
            {
                if (item.Value.Target == obj)
                {
                    ListenerDictionary.Remove(item.Key);
                }
            }
        }

        public void RemoveAll()
        {
            this.ListenerDictionary.Clear();
        }

        public void Dispose()
        {
            this.ListenerDictionary.Clear();
            this.ListenerDictionary = null;
        }
    }
}
